// *********************************************************************************
// Project Name : round robin arbiter 
// Author       : xfsong
// Email        : 1293993416@qq.com
// Create Time  : 2024-05-06
// File Name    : .v
// Module Name  :
// Called By    :
// Abstract     : rr arbiter based on mask one ready-input channel
//
// 
// *********************************************************************************
// Modification History:
// Date         By              Version                 Change Description
// -----------------------------------------------------------------------
// 2024-05-06    Macro           1.0                     Original
//  
// *********************************************************************************

module rr_arbiter2(
    input clk, rst_n,
    input READY0, READY1, READY2, READY3, 
    input READY4, READY5, READY6, READY7,
    output [7:0] GRANT// one-hot ,0000_0000 represents arbiter not working
);

wire [7:0] ready;
assign ready = {READY7, READY6, READY5, READY4, READY3, READY2, READY1, READY0};

wire [7:0] ready_masked;
reg  [7:0] pointer_reg;
assign ready_masked= ready & pointer_reg;

//ready_masked ->fix priority arbiter
wire [7:0] pre_prio_ready_masked;
assign pre_prio_ready_masked[0] = 0;
assign pre_prio_ready_masked[7:1] = ready_masked[6:0] | pre_prio_ready_masked[6:0];
wire [7:0] grant_masked;
assign grant_masked = ready_masked & (~pre_prio_ready_masked);

//general ready_masked ->fix priority arbiter
wire [7:0] pre_prio_ready_general;
assign pre_prio_ready_general[0] = 0;
assign pre_prio_ready_general[7:1] = ready[6:0] | pre_prio_ready_general[6:0];
wire [7:0] grant_general;
assign grant_general = ready & (~pre_prio_ready_general);

//to generate grant
wire no_ready_masked;
assign no_ready_masked = ~(|ready_masked);
assign GRANT = ({8{no_ready_masked}} & grant_general) | grant_masked;

//to generate pointer_reg
always@(posedge clk or negedge rst_n)begin
    if(!rst_n)
        pointer_reg <= 8'b1111_1111;
    else begin
        if(|ready_masked)
            pointer_reg <= pre_prio_ready_masked;
        else begin
            if(|ready)
                pointer_reg <= pre_prio_ready_general;
            //else
              //  pointer_reg <= pointer_reg;
        end
    end
end

endmodule

